/**
 * @file: sample_plugin.cpp
 * @author: sdk team
 * @brief
 * @version: 1.0
 * @date 2022-05-26
 *
 * Copyright:
 * © 2018 北京灵汐科技有限公司 版权所有。
 * 注意：以下内容均为北京灵汐科技有限公司原创，未经本公司允许，不得转载，否则将视为侵权；对于不遵守此声明或者其他违法使用以下内容者，本公司依法保留追究权。
 * © 2018 Lynxi Technologies Co., Ltd. All rights reserved.
 * NOTICE: All information contained here is, and remains the property of Lynxi. This file can not
 * be copied or distributed without the permission of Lynxi Technologies Co., Ltd.
 */

// aarch64-linux-gnu-gcc libPlugin.cpp -g -Wall -fPIC -shared -o libPlugin.so -I
// ~/code/LynchipSDKV2/include/

#include <stdio.h>
#include <sys/time.h>
#include <ctime>
#include <locale>
#include <codecvt>

#include "osd_plugin.h"

#include "unistd.h"

#define USING_TIME(expr)                                                                           \
    do {                                                                                           \
        struct timeval tBegin;                                                                     \
        gettimeofday(&tBegin, 0);                                                                  \
        {                                                                                          \
            expr;                                                                                  \
        }                                                                                          \
        struct timeval tEnd;                                                                       \
        gettimeofday(&tEnd, 0);                                                                    \
        float times = (float) (tEnd.tv_sec - tBegin.tv_sec) * 1000 +                               \
                      (float) (tEnd.tv_usec - tBegin.tv_usec) / 1000;                              \
        LOG_PLUGIN_E("%s using time: %f\n", __FUNCTION__, times);                                  \
    } while (0)


std::wstring UTF8ToWstring(char *text)
{
    static std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    std::wstring wideString = converter.from_bytes(text); // 将UTF-8字符串转换为宽字符串
    return wideString;
}

int DrawBox(void *args)
{
    lynDrawBoxAttr *attr = (lynDrawBoxAttr *) args;

    if (attr->imgW <= attr->thickness * 2 || attr->imgH <= attr->thickness * 2)
        return 0;

    attr->imgData = (uint8_t *) lynPluginGetVirtAddr(attr->imgData);
    lynPluginDrawBox(attr);
    return 0;
}

int DrawText(void *args)
{
    DrawTextPara *para = (DrawTextPara *) args;
    para->attr.imgData = (uint8_t *) lynPluginGetVirtAddr(para->attr.imgData);
    para->attr.text = para->text;
    lynPluginDrawText(&(para->attr));
    return 0;
}

int DrawTextV2(void *args)
{
    DrawTextV2Para *para = (DrawTextV2Para *) args;
    para->attr.imgData = (uint8_t *) lynPluginGetVirtAddr(para->attr.imgData);
    std::wstring wideString = UTF8ToWstring(para->text);
    para->attr.text = const_cast<wchar_t*>(wideString.data());
    lynPluginDrawTextV2(&(para->attr));
    return 0;
}

int lynDrawBoxAndText(lynDrawBoxAndTextPara *para)
{
    int ret = 0;
    uint8_t *imgData = (uint8_t *)lynPluginGetVirtAddr(para->imgData);
    lynBoxesInfo *boxesInfo = (lynBoxesInfo *)lynPluginGetVirtAddr(para->boxesInfo);

    for (uint32_t i = 0; i < boxesInfo->boxesNum; i++) {
        auto& box = boxesInfo->boxes[i];

        if (box.ymax - box.ymin <= para->boxThick * 2 || box.xmax - box.xmin <= para->boxThick * 2) continue;

        lynDrawBoxAttr boxAttr = {box.xmin, box.ymin, box.xmax - box.xmin, box.ymax - box.ymin,
            para->imgW, para->imgH, para->boxThick, para->boxColor, para->imgFmt, imgData};
        ret = lynPluginDrawBox(&boxAttr);
        if (ret != 0) {
            break;
        }
        std::wstring wideString = UTF8ToWstring(box.label);
        lynDrawTextAttrV2 textAttr = {box.xmin, box.ymin, para->imgW, para->imgH, para->imgFmt,
                                    para->fontSize, para->fontColor, imgData, const_cast<wchar_t*>(wideString.data())};
        ret = lynPluginDrawTextV2(&textAttr);
        if (ret != 0) {
            break;
        }
    }

    return ret;
}
